import base64
import datetime
import logging
import os
import traceback
import urllib
from enum import Enum

from flask import request, Response
from flask_restful import Resource, reqparse

from app.commons.check_token import checkIfLogin
from app.commons.ma import ma
from app.commons.pagination import get_page
import urllib.parse
from app.service.merge_data.functions import merge_filename, get_datetime_from_file, \
    get_filename_from_file_with_postfix

parser = reqparse.RequestParser(trim=True)


class FileReqType(Enum):
    ViewList = 1
    Download = 2
    Matchdata = 3
    DeleteFile = 4
    DownloadResult = 5
    ViewLog = 6
    ViewPic = 7
    MatchPic = 8
    DownloadPic = 9
    DeletePic = 10
    MatchPicbysku = 11
    ViewPic_gz = 12
    MatchPic_gz = 13
    DownloadPic_gz = 14
    DeletePic_gz = 15
    MatchPicbysku_gz = 16


class FileRequestArgs(ma.Schema):
    filename = ma.String()
    page = ma.Integer()
    limit = ma.Integer()
    type = ma.Integer()
    date = ma.String()
    merchant_name = ma.String()
    sku = ma.String()


def file_iterator(file_path, chunk_size=512):
    """
        文件读取迭代器
    :param file_path:文件路径
    :param chunk_size: 每次读取流大小
    :return:
    """
    with open(file_path, 'rb') as target_file:
        while True:
            chunk = target_file.read(chunk_size)
            if chunk:
                yield chunk
            else:
                break


class FileView(Resource):

    @staticmethod
    def get_view_list(page, limit, files):
        from app.service.merge_data.functions import isSourceFile
        data = []
        for file in files:
            if not isSourceFile(file):
                continue
            date_full = get_datetime_from_file(file)
            result_file = merge_filename("/result/result.xlsx", date_full)
            status = 1 if os.path.isfile("files/" + result_file) else 0
            filename_without_date = get_filename_from_file_with_postfix(file)
            data.append(
                {"filename": filename_without_date, "status": status, "upload_date": date_full})
        data = sorted(data, key=lambda i: i['upload_date'], reverse=True)
        data, total_size = get_page(page, limit, data)
        return data, total_size

    @staticmethod
    def get_pic_list(page, limit, files):
        data = []
        for file in files:
            if file == "CurrentStock.xlsx" or file.split('.')[1] != "xlsx":
                continue
            date_full = get_datetime_from_file(file)
            data.append(
                {"data": file, "ctime": date_full})
        data = sorted(data, key=lambda i: i['ctime'], reverse=True)
        data, total_size = get_page(page, limit, data)
        return data, total_size

    @staticmethod
    def download_file(filename, date):
        try:
            filename = merge_filename(filename, date)
            system_path = 'files/'
            send_path = os.path.join(system_path, filename)
            if not os.path.isfile(send_path):
                return {"code": 404, "msg": "文件不存在"}
            else:
                response = Response(file_iterator(send_path))
                # response 中转码文件名
                response.headers["Content-Disposition"] = 'attachment;filename="{}"'.format(
                    urllib.parse.quote(filename))
                return response
        except Exception as e:
            traceback.print_exc()
            logging.warning(e)
            return None

    @staticmethod
    def download_pic(filename, userid,region="sh"):
        try:
            system_path = 'files/stock_with_pic/%s/' % (userid)
            if region!="sh":
                system_path = 'files/stock_with_pic/%s/%s/' % (region,userid)
            send_path = os.path.join(system_path, filename)
            if not os.path.isfile(send_path):
                return {"code": 404, "msg": "文件不存在"}
            else:
                response = Response(file_iterator(send_path))
                # response 中转码文件名
                response.headers["Content-Disposition"] = 'attachment;filename="{}"'.format(
                    urllib.parse.quote(filename))
                return response
        except Exception as e:
            traceback.print_exc()
            logging.warning(e)
            return None

    @staticmethod
    def get_log(filename, date):
        try:
            filename = merge_filename(filename, date)
            system_path = 'files/'
            send_path = os.path.join(system_path, filename)
            if not os.path.isfile(send_path):
                return
            else:
                data = open(send_path, 'r', encoding='UTF-8').read()
                return data
        except Exception as e:
            traceback.print_exc()
            logging.warning(e)
            return None

    @staticmethod
    def match_file(filename, date):
        from app.service.merge_data.merge_data import match_result
        match_result(merge_filename(filename, date))
        return {"success": "true"}

    @staticmethod
    def match_picture(userid, merchant_list,region="sh"):
        from app.service.match_picture.exec import match_picture
        match_picture(userid, merchant_list,region)
        return {"success": "true"}

    @staticmethod
    def match_picture_with_sku(userid, sku,region="sh"):
        from app.service.match_picture.exec import match_picture_with_sku
        match_picture_with_sku(userid, sku,region)
        return {"success": "true"}

    @staticmethod
    def delete_file(directory, full_filename, filename):
        if os.path.exists(os.path.join(directory, full_filename)):
            os.remove(os.path.join(directory, full_filename))
        elif os.path.exists(os.path.join(directory, filename)):
            os.remove(os.path.join(directory, full_filename))
        else:
            return

    def get(self):
        try:
            host = ["pjsnkr","wzt123"]
            query_args = FileRequestArgs().dump(request.args)
            request_type = int(query_args["type"])
            cookie = urllib.parse.unquote(str(request.cookies.get('pj_login')))
            username=checkIfLogin(cookie)
            userid = username
            if request_type == FileReqType.ViewList.value:
                page = int(query_args["page"])
                limit = int(query_args["limit"])
                files = os.listdir('files/')
                data = []
                size = 0
                if len(files) > 0:
                    data, size = self.get_view_list(page, limit, files)
                return {"code": 0, "msg": "", "count": size, "data": data}
            elif request_type == FileReqType.Download.value:
                filename = query_args["filename"]
                date = query_args["date"]
                if filename and date:
                    response = self.download_file(filename, date)
                    if response is not None:
                        return response
                return {"code": 500, "msg": "文件服务器错误，请联系管理员"}
            elif request_type == FileReqType.Matchdata.value and str(username) in host:
                filename = query_args["filename"]
                date = query_args["date"]
                self.delete_file('files/', merge_filename("result/result.xlsx", date),
                                 merge_filename("result/result.xlsx", date))
                response = self.match_file(filename, date)
                return response
            elif request_type == FileReqType.DeleteFile.value and str(username) in host:
                filename = query_args["filename"]
                date = query_args["date"]
                directory = 'files/'
                file_list = [filename, "stock/CurrentStock.xlsx", "log/log.txt", "result/result.xlsx",
                             "config/data_config.json"]
                for file in file_list:
                    full_filename = merge_filename(file, date)
                    self.delete_file(directory, full_filename, filename)
                return {"success": "true"}
            elif request_type == FileReqType.DownloadResult.value:
                filename = "result/result.xlsx"
                date = query_args["date"]
                if filename and date:
                    response = self.download_file(filename, date)
                    if response is not None:
                        return response
            elif request_type == FileReqType.ViewLog.value:
                filename = "log/log.txt"
                date = query_args["date"]
                if filename and date:
                    response = self.download_file(filename, date)
                    if response is not None:
                        return response
            elif request_type == FileReqType.ViewPic.value:
                page = int(query_args["page"])
                limit = int(query_args["limit"])
                file_path = 'files/stock_with_pic/%s/' % userid
                if not os.path.exists(file_path):
                    os.makedirs(file_path)
                files = os.listdir('files/stock_with_pic/%s/' % userid)
                data = []
                size = 0
                if len(files) > 0:
                    data, size = self.get_pic_list(page, limit, files)
                return {"code": 0, "msg": "", "count": size, "data": data}
            elif request_type == FileReqType.DownloadPic.value:
                filename = query_args["filename"]
                if filename:
                    response = self.download_pic(filename, userid)
                    if response is not None:
                        return response
            elif request_type == FileReqType.MatchPic.value and str(username) in host:
                merchant_name = query_args["merchant_name"]
                response = self.match_picture(userid, [merchant_name])
                return response
            elif request_type == FileReqType.DeletePic.value and str(username) in host:
                filename = str(query_args["filename"])
                os.remove("files/stock_with_pic/%s/%s" % (userid, filename))
                return {"success": "true"}
            elif request_type == FileReqType.MatchPicbysku.value and str(username) in host:
                sku = query_args["sku"]
                response = self.match_picture_with_sku(userid, sku)
                return response
            elif request_type == FileReqType.ViewPic_gz.value:
                page = int(query_args["page"])
                limit = int(query_args["limit"])
                file_path = 'files/stock_with_pic/gz/%s/' % userid
                if not os.path.exists(file_path):
                    os.makedirs(file_path)
                files = os.listdir('files/stock_with_pic/gz/%s/' % userid)
                data = []
                size = 0
                if len(files) > 0:
                    data, size = self.get_pic_list(page, limit, files)
                return {"code": 0, "msg": "", "count": size, "data": data}
            elif request_type == FileReqType.DownloadPic_gz.value:
                filename = query_args["filename"]
                if filename:
                    response = self.download_pic(filename, userid,"gz")
                    if response is not None:
                        return response
            elif request_type == FileReqType.MatchPic_gz.value and str(username) in host:
                merchant_name = query_args["merchant_name"]
                response = self.match_picture(userid, [merchant_name],"gz")
                return response
            elif request_type == FileReqType.DeletePic_gz.value and str(username) in host:
                filename = str(query_args["filename"])
                os.remove("files/stock_with_pic/gz/%s/%s" % (userid, filename))
                return {"success": "true"}
            elif request_type == FileReqType.MatchPicbysku_gz.value and str(username) in host:
                sku = query_args["sku"]
                response = self.match_picture_with_sku(userid, sku,"gz")
                return response
            else:
                logging.warning("Invalid type when calling /api/file, request_type:%s"%(request_type))
                return {"code": 0, "success": "false", "msg": "参数错误"}
        except Exception as e:
            logging.warning("Exception when calling /api/file GET")
            traceback.print_exc()
            return {"code": 500, "success": "false", "msg": "服务器内部错误，请管理员查看路径是否存在，或先上传文件即可新建路径"}

    def post(self):
        cookie = urllib.parse.unquote(str(request.cookies.get('pj_login')))
        userid = checkIfLogin(cookie)
        host = "pjsnkr"
        if userid and str(userid) == host:
            try:
                contents = request.files.getlist('file')
                directory = 'files/'
                for c in contents:
                    date = str(datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
                    filename = merge_filename(c.filename, date)
                    c.save(os.path.join(directory, filename))
            except Exception as e:
                traceback.print_exc()
                return {"exception": "true"}
            return {"success": "true"}
        else:
            return {"success": "false", "err_msg": "no login"}
